#define THREADED
#include "ZooKeeperUtil.h"
#include "SrpcApplication.h"
#include "SrpcLogger.h"
#include <condition_variable>
#include <mutex>
#include <zookeeper/zookeeper.h>

std::mutex cv_mutex;
std::condition_variable cond;
bool is_connected = false;

// 全局watcher观察器, 用于接收ZooKeeper服务器的消息
void global_watcher(zhandle_t *zh, int type, int status, const char *path,
                    void *watcherCtx) {
  if (type == ZOO_SESSION_EVENT) {
    if (status == ZOO_CONNECTED_STATE) {
      std::lock_guard<std::mutex> lock(cv_mutex);
      is_connected = true;
    }
  }
  cond.notify_all();
}
// 构造函数
ZooKeeperClient::ZooKeeperClient() : m_zhandle(nullptr) {}
// 析构函数
ZooKeeperClient::~ZooKeeperClient() {
  if (m_zhandle != nullptr) {
    zookeeper_close(m_zhandle);
  }
}
// 启动ZooKeeper客户端，连接ZooKeeper服务器
void ZooKeeperClient::Start() {
  std::string host =
      SrpcApplication::GetInstance().GetConfig().Load("zookeeperip");
  std::string port =
      SrpcApplication::GetInstance().GetConfig().Load("zookeeperport");
  std::string connstr = host + ":" + port;
  // zookeeper_init 初始化ZooKeeper客户端对象
  m_zhandle = zookeeper_init(connstr.c_str(), global_watcher, 6000, nullptr,
                             nullptr, 0);
  if (m_zhandle == nullptr) {
    SrpcLogger::ERROR("zookeeper init fail!");
    exit(EXIT_FAILURE);
  }
  // 等待连接成功
  std::unique_lock<std::mutex> lock(cv_mutex);
  cond.wait(lock, [] { return is_connected; });
  SrpcLogger::INFO("zookeeper init success");
}

void ZooKeeperClient::Create(const std::string &path, const std::string &data,
                             int state) {
  char path_buffer[128];
  int buffer_len = sizeof(path_buffer);
  // 判断节点是否存在
  int flag = zoo_exists(m_zhandle, path.c_str(), 0, nullptr);
  if (flag == ZNONODE) {
    // 创建节点
    flag = zoo_create(m_zhandle, path.c_str(), data.c_str(), data.length(),
                      &ZOO_OPEN_ACL_UNSAFE, state, path_buffer, buffer_len);
    if (flag == ZOK) {
      SrpcLogger::INFO("znode create success! path: " + path);
    } else {
      SrpcLogger::INFO("znode create failed! path: " + path);
      exit(EXIT_FAILURE);
    }
  }
}

std::string ZooKeeperClient::GetData(const std::string &path) {
  char buf[64];
  int buffer_len = sizeof(buf);
  // 获取指定节点的数据
  int flag = zoo_get(m_zhandle, path.c_str(), 0, buf, &buffer_len, nullptr);
  if (flag != ZOK) {
    SrpcLogger::ERROR("zoo_get error. path: " + path);
    return "";
  } else {
    return buf;
  }
  return "";
}